﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Collections.Specialized;

namespace XMLDocGen
{
    public partial class frmMain : Form
    {
        Assembly loadedAssembly = null;

        public frmMain()
        {
            InitializeComponent();
        }

        private void mnuImportAssembly_Click(object sender, EventArgs e)
        {
            if (ofdAssembly.ShowDialog() == DialogResult.OK)
            {
                if (File.Exists(ofdAssembly.FileName))
                {
                    splitContainer1.Visible = true;
                    PopulateTreeview(ofdAssembly.FileName);
                }
            }
        }

        private void PopulateTreeview(string filename)
        {
            loadedAssembly = Assembly.LoadFrom(filename);

            Type[] types = loadedAssembly.GetExportedTypes();

            List<String> namespaces = new List<String>();

            foreach (Type t in types)
            {
                if (!namespaces.Contains(t.Namespace))
                {
                    namespaces.Add(t.Namespace);
                }
            }

            tvwTypes.BeginUpdate();

            foreach (string namespc in namespaces.OrderBy(s => s))
            {
                TreeNode node = new TreeNode(namespc);
                node.Name = namespc;

                tvwTypes.Nodes.Add(node);
            }

            foreach (Type t in types)
            {
                foreach (TreeNode namespaceNodes in tvwTypes.Nodes)
                {
                    if (namespaceNodes.Name == t.Namespace)
                    {
                        TreeNode node = new TreeNode(t.Name);
                        node.Name = t.FullName;
                        namespaceNodes.Nodes.Add(node);
                        namespaceNodes.Expand();
                    }
                }
            }

            tvwTypes.EndUpdate();
        }

        private void tvwTypes_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Node.Name))
            {
                PopulateDataView(e.Node.Name);
            }
        }

        private void PopulateDataView(string typeName)
        {
            if (loadedAssembly != null)
            {
                Type t = loadedAssembly.GetExportedTypes().SingleOrDefault(a => a.FullName == typeName);



                if (t != null)
                {
                    // Clear the DataGridView
                    grdProperties.Rows.Clear();

                    // Check if the Type is an enum.
                    if (t.IsEnum)
                    {
                        SetupEnumColumns(t.FullName);

                        FieldInfo[] infos = t.GetFields(BindingFlags.Public | BindingFlags.Static); ;

                        foreach (FieldInfo f in infos)
                        {
                            grdProperties.Rows.Add(new object[] { f.Name });
                        }

                    }
                    else
                    {
                        SetupClassColumns(t.FullName);

                        foreach (PropertyInfo propinfo in t.GetProperties().OrderBy(p => p.Name))
                        {
                            Type propertyType = propinfo.PropertyType;

                            if (propertyType.IsGenericType)
                            {
                                Type genericType = propertyType.GetGenericTypeDefinition();
                                Type[] genericTypeArgs = propertyType.GetGenericArguments();
                                string genericFullname = genericType.FullName;

                                if (genericTypeArgs.Length > 0)
                                {
                                    genericFullname = genericFullname.Substring(0, genericFullname.Length - 2);
                                }

                                StringBuilder sb = new StringBuilder();

                                sb.Append(genericFullname + " <");

                                for (int i = 0; i < genericTypeArgs.Length; i++)
                                {
                                    if (i > 0)
                                    {
                                        sb.Append(", ");
                                    }

                                    sb.Append(genericTypeArgs[i].Name);
                                }

                                sb.Append(">");

                                grdProperties.Rows.Add(new object[] { propinfo.Name, sb.ToString() });
                            }
                            else
                            {
                                grdProperties.Rows.Add(new object[] { propinfo.Name, propertyType.FullName });
                            }
                        }
                    }
                }
            }
        }

        private void SetupClassColumns(string type)
        {
            grdProperties.Columns.Clear();
            DataGridViewTextBoxColumn nameCol = new DataGridViewTextBoxColumn();

            nameCol.HeaderText = "Name.";
            nameCol.Name = "nameCol";
            nameCol.ReadOnly = true;

            grdProperties.Columns.Add(nameCol);

            DataGridViewTextBoxColumn typeCol = new DataGridViewTextBoxColumn();

            typeCol.HeaderText = "Type.";
            typeCol.Name = "typeCol";
            typeCol.ReadOnly = true;

            grdProperties.Columns.Add(typeCol);

            label1.Text = "Class " + type;
        }

        private void SetupEnumColumns(string typeName)
        {
            grdProperties.Columns.Clear();
            DataGridViewTextBoxColumn nameCol = new DataGridViewTextBoxColumn();

            nameCol.HeaderText = "Name.";
            nameCol.Name = "nameCol";
            nameCol.ReadOnly = true;

            grdProperties.Columns.Add(nameCol);

            label1.Text = "Enum " + typeName;
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            splitContainer1.Visible = false;
        }
    }
}